package com.eco.fanliapp.shengyaappeurekeclient.controller;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eco.fanliapp.shengyaappeurekeclient.entity.AppGoods;
import com.eco.fanliapp.shengyaappeurekeclient.utils.GetDocument;
import com.eco.fanliapp.shengyaappeurekeclient.utils.LuceneUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.web.bind.annotation.*;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.*;


@RestController
@RequestMapping("/eureke/lucene")
@Slf4j
public class LuceneController {

    @Autowired
    private LuceneUtil luceneUtil;

    @Autowired
    private GetDocument getDocument;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 假如这个客户端要提供一个getUser的方法
     *
     * @return
     */
    @GetMapping(value = "/getUser")
    @ResponseBody
    public Map<String, Object> getUser(@RequestParam Integer id) {
        Map<String, Object> data = new HashMap<>();
        data.put("id", id);
        data.put("userName", "admin");
        data.put("from", "provider-B");
        return data;
    }

    /**
     * @param keyword
     * @param sort
     * @param pageSize
     * @param pageNum
     * @return 商品本地搜索
     */
    @PostMapping(value = "/findIndex")
    @ResponseBody
    public IPage<AppGoods> findIndex(String keyword, String sort, Integer pageSize, Integer pageNum, String fqcat) {
        try {
            redisTemplate.setKeySerializer(RedisSerializer.string());
            redisTemplate.setHashKeySerializer(RedisSerializer.string());
            redisTemplate.setHashValueSerializer(RedisSerializer.json());
            redisTemplate.setValueSerializer(RedisSerializer.json());

            BooleanQuery.Builder query = new BooleanQuery.Builder();
            Query query1 = new WildcardQuery(new Term("itemtitle", "*" + keyword + "*"));
            Query query2 = new WildcardQuery(new Term("itemshorttitle", "*" + keyword + "*"));
            Query query3 = new WildcardQuery(new Term("itemdesc", "*" + keyword + "*"));

            query.add(query1, BooleanClause.Occur.SHOULD);
            query.add(query2, BooleanClause.Occur.SHOULD);
            query.add(query3, BooleanClause.Occur.SHOULD);
            BooleanQuery.Builder queryfqcat = new BooleanQuery.Builder();
            if (!org.springframework.util.StringUtils.isEmpty(fqcat)) {
                Query query4 = new WildcardQuery(new Term("fqcat", fqcat));
                queryfqcat.add(query4, BooleanClause.Occur.MUST);
            }
            queryfqcat.add(query.build(), BooleanClause.Occur.MUST);

            if (StringUtils.isEmpty(sort)) {
                sort = "total_sales";
            }
            Sort sorts = null;
            if (sort.contains("_des")) {
                sort = sort.replace("_des", "");
                sorts = luceneUtil.getSortByFloatField(sort, true);//ture降序
            } else if (sort.contains("_asc")) {
                sort = sort.replace("_asc", "");
                sorts = luceneUtil.getSortByFloatField(sort, false);//ture降序
            } else {
                sorts = luceneUtil.getSortByFloatField(sort, true);//ture降序
            }
            TopDocs topDocs = null;

            String dir = null;
            String pathKey = "lucenePath";
            if (redisTemplate.hasKey(pathKey)) {
                Map<String, String> map = (Map) redisTemplate.opsForValue().get(pathKey);
                dir = map.get("oldPath");
            }
            if (!org.springframework.util.StringUtils.isEmpty(fqcat)) {
                topDocs = luceneUtil.getIndexSearcher(dir).search(queryfqcat.build(), 1000, sorts);
            } else {
                topDocs = luceneUtil.getIndexSearcher(dir).search(query.build(), 1000, sorts);
            }

            //查询到的记录数
            long total = topDocs.totalHits;
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            List<AppGoods> appGoods = new ArrayList<>();

            for (int i = (pageNum - 1) * pageSize; i < ((pageNum - 1) * pageSize + pageSize > total ? total : (pageNum - 1) * pageSize + pageSize); i++) {
                Map<String, String> map = new HashMap();
                //取得对应的文档对象
                Document document = luceneUtil.getIndexSearcher(dir).doc(scoreDocs[i].doc);
                appGoods.add(JSON.parseObject(document.get("itemObject"), AppGoods.class));

            }
            IPage<AppGoods> page = new Page<>(pageNum, pageSize, total);
            page.setRecords(appGoods);

            return page;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new Page<>(pageNum, pageSize, 0);
    }

    /*
     * 添加索引
     */
    @PostMapping(value = "/addIndex")
    @ResponseBody
    public int addIndex(@RequestBody String appGoods, IndexWriter indexWriter, String dir) {
        try {
            if (appGoods != null) {
                log.info("添加索引" + appGoods);
                //查看是否存在索引
                AppGoods goods = JSONObject.parseObject(appGoods, AppGoods.class);
                Query query = new TermQuery(new Term("itemid", goods.getItemid()));
                TopDocs hits = luceneUtil.getIndexSearcher(dir).search(query, 2);
                //显示结果数量
                Long i = hits.totalHits;

                Document doc = getDocument.getDocument(goods);
                if (doc == null) {
                    return 0;
                }
                long count = 0L;
                if (i > 0) {
                    count = indexWriter.updateDocument(new Term("itemid", goods.getItemid()), doc);
                } else {
                    count = indexWriter.addDocument(doc);
                }
                indexWriter.commit();
                if (count > 0L) {
                    log.info("添加索引成功");
                    return 1;
                } else {
                    log.info(goods.getItemid() + "添加索引失败");
                    return 0;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    //更新索引
    @PostMapping(value = "/updateIndex")
    @ResponseBody
    public int updateIndex(@RequestBody String appGoods, IndexWriter indexWriter) {

        try {
            if (appGoods != null) {
                log.info("更新索引" + appGoods);
                AppGoods goods = JSONObject.parseObject(appGoods, AppGoods.class);
                if (goods.getItemid() != null || goods.getItemid() != "") {
                    Document doc = getDocument.getDocument(goods);
                    if (doc == null) {
                        log.info(goods.getItemid() + "更新索引失败");
                        return 0;
                    }
                    long count = indexWriter.updateDocument(new Term("itemid", goods.getItemid()), doc);
                    indexWriter.commit();
                    if (count > 0L) {
                        log.info("更新索引成功");
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 删除文档
     *
     * @throws IOException
     */
    @PostMapping(value = "/deleteIndex")
    @ResponseBody
    public int deleteIndex(@RequestBody String appGoods, String dir) {
        try {
            Analyzer analyzer = new IKAnalyzer();//中文分词
            //创建索引写入配置
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
            //创建索引写入对象
            IndexWriter indexWriter = new IndexWriter(luceneUtil.getDirectory(dir), indexWriterConfig);
            if (appGoods != null) {
                log.info("更新索引" + appGoods);
                AppGoods goods = JSONObject.parseObject(appGoods, AppGoods.class);
                if (goods.getItemid() != null || goods.getItemid() != "") {
                    log.info("删除索引" + goods.getItemid());
                    Query query = new TermQuery(new Term("itemid", goods.getItemid()));
                    TopDocs hits = luceneUtil.getIndexSearcher(dir).search(query, 2);
                    //显示结果数量
                    Long i = hits.totalHits;
                    if (i > 0) {
                        long count = indexWriter.deleteDocuments(new Term("itemid", goods.getItemid()));
                        indexWriter.commit();
                        if (count > 0L) {
                            log.info("删除索引成功");
                            return 1;
                        } else {
                            return 0;
                        }
                    } else {
                        log.info(goods.getItemid() + "索引不存在");
                        return 2;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    @PostMapping(value = "/deleteIndexs")
    @ResponseBody
    public int deleteIndexs(@RequestBody String itemids, IndexWriter indexWriter, String dir) {
        try {
            if (itemids != null) {
                log.info("删除索引" + itemids);
                String[] itemid = itemids.split(",");
                for (int i = 0; i < itemid.length; i++) {
                    Query query = new TermQuery(new Term("itemid", itemid[i]));
                    TopDocs hits = luceneUtil.getIndexSearcher(dir).search(query, 2);
                    //显示结果数量
                    Long hit = hits.totalHits;
                    if (hit > 0) {
                        // 删除
                        long count = indexWriter.deleteDocuments(new Term("itemid", itemid[i]));
                        indexWriter.commit();
                        if (count > 0L) {
                            log.info("索引删除成功");
                            return 1;
                        } else {
                            log.info(itemid[i] + "删除索引失败");
                            return 0;
                        }
                    } else {
                        log.info(itemid[i] + "索引不存在");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    //推荐列表
    @PostMapping(value = "/getRecommendGoods")
    @ResponseBody
    public IPage<AppGoods> getRecommendGoods(Integer pageSize, Integer pageNum) {
        try {
            BooleanQuery.Builder query = new BooleanQuery.Builder();
            Query query1 = new WildcardQuery(new Term("recommend", 0 + "*"));
            Query query2 = new WildcardQuery(new Term("itemTop", "1"));
            query.add(query1, BooleanClause.Occur.MUST);
            query.add(query2, BooleanClause.Occur.MUST);

            String dir = null;
            Sort sorts = luceneUtil.getSortByFloatField("tk_total_commi", true);//ture降序
            TopDocs topDocs = luceneUtil.getIndexSearcher(dir).search(query.build(), 1000, sorts);

            //查询到的记录数
            long total = topDocs.totalHits;
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            List<AppGoods> appGoods = new ArrayList<>();

            for (int i = (pageNum - 1) * pageSize; i < ((pageNum - 1) * pageSize + pageSize > total ? total : (pageNum - 1) * pageSize + pageSize); i++) {
                Map<String, String> map = new HashMap();
                //取得对应的文档对象
                Document document = luceneUtil.getIndexSearcher(dir).doc(scoreDocs[i].doc);
                appGoods.add(JSON.parseObject(document.get("itemObject"), AppGoods.class));

            }
            IPage<AppGoods> page = new Page<>(pageNum, pageSize, total);
            page.setRecords(appGoods);

            return page;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new Page<>(pageNum, pageSize, 0);
    }

    //首页分类列表
    @PostMapping(value = "/getClassifyGoodsList")
    @ResponseBody
    public IPage<AppGoods> getClassifyGoodsList(Integer pageSize, Integer pageNum, Integer cid, String sort) {
        try {
            BooleanQuery.Builder query = new BooleanQuery.Builder();
            Query query1 = new WildcardQuery(new Term("fqcat", cid.toString()));
            Query query2 = new WildcardQuery(new Term("itemTop", "1"));
            query.add(query1, BooleanClause.Occur.MUST);
            query.add(query2, BooleanClause.Occur.MUST);

            String dir = null;
            Sort sorts = null;
            if (sort.contentEquals("recommend")) {
                sorts = luceneUtil.getSortByFloatField("recommend", true);//ture降序
            } else if (sort.contentEquals("sales")) {
                sorts = luceneUtil.getSortByFloatField("total_sales", true);//ture降序 销量
            } else {
                sorts = luceneUtil.getSortByFloatField("tk_total_commi", true);//ture降序  更新时间
            }
            TopDocs topDocs = luceneUtil.getIndexSearcher(dir).search(query.build(), 1000, sorts);

            //查询到的记录数
            long total = topDocs.totalHits;
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            List<AppGoods> appGoods = new ArrayList<>();

            for (int i = (pageNum - 1) * pageSize; i < ((pageNum - 1) * pageSize + pageSize > total ? total : (pageNum - 1) * pageSize + pageSize); i++) {
                Map<String, String> map = new HashMap();
                //取得对应的文档对象
                Document document = luceneUtil.getIndexSearcher(dir).doc(scoreDocs[i].doc);
                appGoods.add(JSON.parseObject(document.get("itemObject"), AppGoods.class));

            }
            IPage<AppGoods> page = new Page<>(pageNum, pageSize, total);
            page.setRecords(appGoods);

            return page;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new Page<>(pageNum, pageSize, 0);
    }


    @PostMapping(value = "/findKeyword")
    @ResponseBody
    public Set findKeyword(String keyword) {

        try {
            Directory directory = FSDirectory.open(Paths.get("/home/nginx/fanli/lucene/related"));

            IndexReader indexReader = DirectoryReader.open(directory);
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);
            QueryParser queryParser = new QueryParser(luceneUtil.TEXT_FIELD, new IKAnalyzer(true));
            Query query = queryParser.parse(keyword);
            TopDocs td = indexSearcher.search(query, 10);
            ScoreDoc[] sd = td.scoreDocs;
//            String relateWords[] = new String[sd.length];
            Set relateWords = new HashSet<>();
            for (int i = 0; i < sd.length; i++) {
                int z = sd[i].doc;
                Document doc = indexSearcher.doc(z);
                relateWords.add(doc.get(luceneUtil.TEXT_FIELD));
            }
            indexReader.close();
            directory.close();
            return relateWords;
        } catch (Exception e) {
        }
        return null;
    }


    public static void main(String[] args) {
        try {
            String path = LuceneController.class.getResource("/").getPath();
            String string;
            BufferedReader bufferedReader = new BufferedReader(new FileReader(LuceneController.class.getResource("/").getPath() + "/test.txt"));
            while ((string = bufferedReader.readLine()) != null) {
               log.info(string);
            }
           log.info(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
